package com.bankcard.bininfo.model;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public final class Countries {
    private static final Map<String, CountryInfo> COUNTRIES = new ConcurrentHashMap<>();

    public static final CountryInfo CHINA = new CountryInfo("China", "CN", "CHN", "CNY");
    public static final CountryInfo UNITED_STATES = new CountryInfo("United States", "US", "USA", "USD");
    public static final CountryInfo HONG_KONG = new CountryInfo("Hong Kong", "HK", "HKG", "HKD");
    public static final CountryInfo TAIWAN = new CountryInfo("Taiwan", "TW", "TWN", "TWD");
    public static final CountryInfo SINGAPORE = new CountryInfo("Singapore", "SG", "SGP", "SGD");
    public static final CountryInfo JAPAN = new CountryInfo("Japan", "JP", "JPN", "JPY");
    public static final CountryInfo FRANCE = new CountryInfo("France", "FR", "FRA", "EUR");
    public static final CountryInfo UNITED_KINGDOM = new CountryInfo("United Kingdom", "GB", "GBR", "GBP");
    public static final CountryInfo GERMANY = new CountryInfo("Germany", "DE", "DEU", "EUR");
    public static final CountryInfo CANADA = new CountryInfo("Canada", "CA", "CAN", "CAD");
    public static final CountryInfo AUSTRALIA = new CountryInfo("Australia", "AU", "AUS", "AUD");
    public static final CountryInfo INDIA = new CountryInfo("India", "IN", "IND", "INR");
    public static final CountryInfo BRAZIL = new CountryInfo("Brazil", "BR", "BRA", "BRL");
    public static final CountryInfo SOUTH_AFRICA = new CountryInfo("South Africa", "ZA", "ZAF", "ZAR");
    public static final CountryInfo ITALY = new CountryInfo("Italy", "IT", "ITA", "EUR");
    public static final CountryInfo SPAIN = new CountryInfo("Spain", "ES", "ESP", "EUR");
    public static final CountryInfo MEXICO = new CountryInfo("Mexico", "MX", "MEX", "MXN");
    public static final CountryInfo RUSSIA = new CountryInfo("Russia", "RU", "RUS", "RUB");
    public static final CountryInfo SOUTH_KOREA = new CountryInfo("South Korea", "KR", "KOR", "KRW");
    public static final CountryInfo NETHERLANDS = new CountryInfo("Netherlands", "NL", "NLD", "EUR");
    public static final CountryInfo SWEDEN = new CountryInfo("Sweden", "SE", "SWE", "SEK");
    public static final CountryInfo NORWAY = new CountryInfo("Norway", "NO", "NOR", "NOK");
    public static final CountryInfo SWITZERLAND = new CountryInfo("Switzerland", "CH", "CHE", "CHF");
    public static final CountryInfo ARGENTINA = new CountryInfo("Argentina", "AR", "ARG", "ARS");
    public static final CountryInfo CHILE = new CountryInfo("Chile", "CL", "CHL", "CLP");
    public static final CountryInfo COLOMBIA = new CountryInfo("Colombia", "CO", "COL", "COP");
    public static final CountryInfo PERU = new CountryInfo("Peru", "PE", "PER", "PEN");
    public static final CountryInfo NEW_ZEALAND = new CountryInfo("New Zealand", "NZ", "NZL", "NZD");
    public static final CountryInfo SAUDI_ARABIA = new CountryInfo("Saudi Arabia", "SA", "SAU", "SAR");
    public static final CountryInfo TURKEY = new CountryInfo("Turkey", "TR", "TUR", "TRY");
    public static final CountryInfo POLAND = new CountryInfo("Poland", "PL", "POL", "PLN");
    public static final CountryInfo EGYPT = new CountryInfo("Egypt", "EG", "EGY", "EGP");
    public static final CountryInfo NIGERIA = new CountryInfo("Nigeria", "NG", "NGA", "NGN");
    public static final CountryInfo KENYA = new CountryInfo("Kenya", "KE", "KEN", "KES");
    public static final CountryInfo THAILAND = new CountryInfo("Thailand", "TH", "THA", "THB");
    public static final CountryInfo MALAYSIA = new CountryInfo("Malaysia", "MY", "MYS", "MYR");
    public static final CountryInfo INDONESIA = new CountryInfo("Indonesia", "ID", "IDN", "IDR");
    public static final CountryInfo PHILIPPINES = new CountryInfo("Philippines", "PH", "PHL", "PHP");
    public static final CountryInfo VIETNAM = new CountryInfo("Vietnam", "VN", "VNM", "VND");
    public static final CountryInfo PAKISTAN = new CountryInfo("Pakistan", "PK", "PAK", "PKR");
    public static final CountryInfo BANGLADESH = new CountryInfo("Bangladesh", "BD", "BGD", "BDT");
    public static final CountryInfo SRI_LANKA = new CountryInfo("Sri Lanka", "LK", "LKA", "LKR");
    public static final CountryInfo NEPAL = new CountryInfo("Nepal", "NP", "NPL", "NPR");
    public static final CountryInfo BHUTAN = new CountryInfo("Bhutan", "BT", "BTN", "BTN");
    public static final CountryInfo MALDIVES = new CountryInfo("Maldives", "MV", "MDV", "MVR");
    public static final CountryInfo FIJI = new CountryInfo("Fiji", "FJ", "FJI", "FJD");
    public static final CountryInfo PAPUA_NEW_GUINEA = new CountryInfo("Papua New Guinea", "PG", "PNG", "PGK");

    static {
        // Hardcoded country data
        register(UNITED_STATES);
        register(CHINA);
        register(HONG_KONG);
        register(TAIWAN);
        register(SINGAPORE);
        register(JAPAN);
        register(FRANCE);
        register(UNITED_KINGDOM);
        register(GERMANY);
        register(CANADA);
        register(AUSTRALIA);
        register(INDIA);
        register(BRAZIL);
        register(SOUTH_AFRICA);
        register(ITALY);
        register(SPAIN);
        register(MEXICO);
        register(RUSSIA);
        register(SOUTH_KOREA);
        register(NETHERLANDS);
        register(SWEDEN);
        register(NORWAY);
        register(SWITZERLAND);
        register(ARGENTINA);
        register(CHILE);
        register(COLOMBIA);
        register(PERU);
        register(NEW_ZEALAND);
        register(SAUDI_ARABIA);
        register(TURKEY);
        register(POLAND);
        register(EGYPT);
        register(NIGERIA);
        register(KENYA);
        register(THAILAND);
        register(MALAYSIA);
        register(INDONESIA);
        register(PHILIPPINES);
        register(VIETNAM);
        register(PAKISTAN);
        register(BANGLADESH);
        register(SRI_LANKA);
        register(NEPAL);
        register(BHUTAN);
        register(MALDIVES);
        register(FIJI);
        register(PAPUA_NEW_GUINEA);
        // Add more countries as needed
    }

    private Countries() {}

    /**
     * Loads country information from a JSON string.
     *
     * @param json A JSON string containing an array of country information objects.
     *             Each object should include the country's alpha-2 code, alpha-3 code,
     *             numeric code, and name.
     *
     * @throws RuntimeException if the JSON parsing fails
     *
     * <p>Example JSON input:
     * <pre>
     * [
     *   {
     *     "isoCountryName": "United States",
     *     "isoCountryCodeA2": "US",
     *     "isoCountryCodeA3": "USA",
     *     "isoCountryCurrency": "USD"
     *   },
     *   {
     *     "isoCountryName": "Canada",
     *     "isoCountryCodeA2": "CA",
     *     "isoCountryCodeA3": "CAN",
     *     "isoCountryCurrency": "CAD"
     *   }
     * ]
     * </pre>
     */
    public static void loadCountries(String json) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            List<CountryInfo> countries = mapper.readValue(json, new TypeReference<List<CountryInfo>>() {});
            for (CountryInfo country : countries) {
                register(country);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to load countries from JSON", e);
        }
    }

    private static void register(CountryInfo countryInfo) {
        COUNTRIES.putIfAbsent(countryInfo.getIsoCountryCodeA3().toUpperCase(), countryInfo);
    }

    public static CountryInfo getByAlpha3Code(String alpha3Code) {
        return COUNTRIES.values().stream()
                .filter(country -> country.getIsoCountryCodeA3().equalsIgnoreCase(alpha3Code))
                .findFirst()
                .orElse(null);
    }
}